package com.ruoyi.syf.service.impl;

import java.util.Date;
import java.util.List;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.annotation.ConvertField;
import com.ruoyi.common.annotation.ConvertFieldItem;
import com.ruoyi.syf.common.constant.DangerSource;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.ConvertType;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.syf.domain.RiskCheckDanger;
import com.ruoyi.syf.domain.RiskCheckRecord;
import com.ruoyi.syf.domain.RiskCheckTask;
import com.ruoyi.syf.domain.vo.RiskCheckVo;
import com.ruoyi.syf.mapper.RiskCheckRecordMapper;
import com.ruoyi.syf.common.constant.Check;
import com.ruoyi.syf.handler.task.TaskFactory;
import com.ruoyi.syf.domain.vo.RiskMeasureVo;
import com.ruoyi.syf.mapper.RiskMeasureMapper;
import com.ruoyi.syf.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 排查记录Service业务层处理
 *
 * @author yr
 * @date 2024-07-31
 */
@Service
public class RiskCheckRecordServiceImpl extends ServiceImpl<RiskCheckRecordMapper, RiskCheckRecord> implements IRiskCheckRecordService {

    @Lazy
    @Autowired
    private IRiskCheckTaskService taskService;
    @Autowired
    private IRiskAnalysisUnitService unitService;
    @Autowired
    private IRiskCheckDangerService dangerService;
    @Autowired
    private IRiskCheckDangerFixService fixService;
    @Autowired
    private TaskFactory taskFactory;
    @Autowired
    private RiskCheckRecordMapper riskCheckRecordMapper;
    @Autowired
    private RiskMeasureMapper measureMapper;


    @ConvertField({
            @ConvertFieldItem(fieldName = "source", dictType = "danger_source", type = ConvertType.DICT),
            @ConvertFieldItem(fieldName = "checkBy", assistFieldName = "checkByName", type = ConvertType.USER)
    })
    @Override
    public List<RiskCheckVo> list(RiskCheckVo vo) {
        vo.setLoginUserId(SecurityUtils.getUserId());
        return riskCheckRecordMapper.list(vo);
    }

    @Override
    public RiskCheckVo getInfo(Long id) {
        RiskCheckVo vo = riskCheckRecordMapper.getInfo(id);
        if (vo.getImei() == null) vo.setImei(unitService.getById(vo.getUnitId()).getImei());
        LambdaQueryWrapper<RiskCheckDanger> lqw = new LambdaQueryWrapper<>();
        lqw.eq(RiskCheckDanger::getRecordId, id)
                .eq(RiskCheckDanger::getDelFlag, 0);
        RiskCheckDanger danger = dangerService.getOne(lqw);
        vo.setCheckDanger(danger);
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void taskSave(RiskCheckTask task) throws IllegalAccessException {
        Date checkBeginTime = new Date(task.getNextActualStartTime().getTime() - (task.getExcursionTime() / 1000) * 1000);
        //新增排查记录
        taskSave(task, checkBeginTime);

        //计算并更新排查定时任务下一轮执行时间
        Date lastBeginTime = taskFactory.getNextBeginTime(
                task.getCycleType(),
                task.getNextActualStartTime(),
                task.getActualStartTime(),
                task.getCycle(),
                task.getCycleUnit());
        task.setNextActualStartTime(lastBeginTime);
        taskService.updateById(task);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savePreviousPeriods(RiskCheckTask task) throws IllegalAccessException {
        Long taskId = task.getId();
        String cycleType = task.getCycleType();
        Date checkBeginTime = task.getStartTime();
        Integer cycle = task.getCycle();
        String cycleUnit = task.getCycleUnit();
        Integer num = task.getPreviousPeriodsNum();
        while (num > 0) {
            //计算上一周期隐患排查开始时间
            checkBeginTime = taskFactory.getLastBeginTime(cycleType, checkBeginTime, cycle, cycleUnit);
            //校验是否已生成
            List<RiskCheckRecord> list = list(new LambdaQueryWrapper<RiskCheckRecord>()
                    .eq(RiskCheckRecord::getTaskId, taskId)
                    .eq(RiskCheckRecord::getCheckBeginTime, checkBeginTime)
                    .eq(RiskCheckRecord::getDelFlag, "0"));
            if (list.isEmpty()) {
                taskSave(task, checkBeginTime);
            }
            num--;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean mySave(RiskCheckVo vo) {
        //如果imei号为空则设置为单元绑定的默认imei号
        if (vo.getImei() == null) {
            vo.setImei(unitService.getById(vo.getUnitId()).getImei());
        }
        //pc端自主进行选择，手机端自动获取当前登录用户
        if (vo.getCheckBy() == null) {
            LoginUser loginUser = SecurityUtils.getLoginUser();
            vo.setCheckDept(loginUser.getDeptId());
            vo.setCheckBy(loginUser.getUserId());
        }
        //pc端自主进行选择，手机端自动获取当前时间
        if (vo.getCheckTime() == null) {
            Date date = new Date();
            vo.setCheckTime(date);
            vo.setCheckBeginTime(date);
            vo.setCheckEndTime(date);
        } else {
            vo.setCheckBeginTime(vo.getCheckTime());
            vo.setCheckEndTime(vo.getCheckTime());
        }

        vo.setCheckStatus(Check.CheckInfo.C_TO_CONFIRM.getCode());
        vo.setIsDefend("0");//默认非包保责任人任务
        vo.setResult("1");//手动新增一定存在隐患
        riskCheckRecordMapper.insert(vo);

        //新增隐患记录
        dangerService.mySave(vo.getCheckDanger(), vo.getId());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean myUpdate(RiskCheckVo vo) throws IllegalAccessException {
        RiskCheckRecord record = getById(vo.getId());
        //校验排查状态
        Check.checkEqualsStatus(record.getCheckStatus(), Check.CheckInfo.C_BACK);
        //校验权限
        SecurityUtils.hasUser(record.getCheckBy());
        //更新排查信息
        vo.setCheckTime(DateUtils.getNowDate());
        String oldResult = record.getResult();
        String result = vo.getResult();
        vo.setCheckStatus("1".equals(result) ? Check.CheckInfo.C_TO_CONFIRM.getCode()
                : Check.CheckInfo.C_ALREADY.getCode());
        riskCheckRecordMapper.updateById(vo);

        if (result.equals("0")) {//排查结果不存在隐患
            if ("1".equals(oldResult)) {//原排查结果存在隐患，删除
                dangerService.deleteRiskCheckDangerById(vo.getCheckDanger().getId());
            }
        } else {//排查结果存在隐患
            if ("1".equals(oldResult)) {//原排查结果存在隐患，修改
                dangerService.updateById(vo.getCheckDanger());
            } else {//原排查结果不存在隐患，新增
                dangerService.mySave(vo.getCheckDanger(), vo.getId());
            }
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean check(RiskCheckVo vo) throws IllegalAccessException {
        RiskCheckRecord record = getById(vo.getId());
        //校验排查状态
        Check.checkEqualsStatus(record.getCheckStatus(), Check.CheckInfo.C_NO);
        //校验主任务
        RiskCheckTask task = taskService.getById(record.getTaskId());
        if (task == null) {
            throw new IllegalAccessException("排查定时任务被删除!");
        }
        List<Long> checkBys = JSON.parseArray(task.getCheckBys(), Long.class);
        //校验权限
        SecurityUtils.hasUsers(checkBys);
        //校验是否仅扫码排查
        unitService.isScan(record.getUnitId());
        //校验排查时间：判断当前时间是否大于任务开始时间
        Date date = new Date();
        if (date.compareTo(record.getCheckBeginTime()) < 0) {
            throw new IllegalAccessException("未到排查时间!");
        } else {
            vo.setCheckTime(date);
        }

        //更新排查信息
        if (vo.getCheckBy() == null) vo.setCheckBy(SecurityUtils.getUserId());
        String result = vo.getResult();
        vo.setCheckStatus("1".equals(result) ? Check.CheckInfo.C_TO_CONFIRM.getCode()
                : Check.CheckInfo.C_ALREADY.getCode());
        riskCheckRecordMapper.updateById(vo);
        //判断是否为（定时任务启用状态 && 当前排查任务为最新的），是则新增下一周期的排查任务
        if (task.getStatus() &&
                getBeginCheckTimeByTaskId(record.getTaskId()).compareTo(record.getCheckBeginTime()) == 0) {
            taskSave(task);
        }
        //新增隐患
        if ("1".equals(result)) {
            dangerService.mySave(vo.getCheckDanger(), vo.getId());
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean normal(RiskCheckVo vo) throws IllegalAccessException {
        vo.setResult("0");
        return check(vo);
    }

    @Override
    public boolean backById(Long id) throws IllegalAccessException {
        RiskCheckRecord record = getById(id);
        //校验排查状态
        Check.checkEqualsStatus(record.getCheckStatus(), Check.CheckInfo.C_TO_CONFIRM, Check.CheckInfo.C_FORWARD);
        //校验权限
        RiskCheckDanger danger = dangerService.getByRecordId(id);
        SecurityUtils.hasUser(danger.getFixBy());
        //修改排查状态
        record.setCheckStatus(Check.CheckInfo.C_BACK.getCode());
        return updateById(record);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean confirmById(Long id) throws IllegalAccessException {
        RiskCheckRecord record = getById(id);
        //校验排查状态
        Check.checkEqualsStatus(record.getCheckStatus(), Check.CheckInfo.C_TO_CONFIRM, Check.CheckInfo.C_FORWARD);
        //校验权限
        RiskCheckDanger danger = dangerService.getByRecordId(id);
        SecurityUtils.hasUser(danger.getFixBy());
        //修改排查状态
        record.setCheckStatus(Check.CheckInfo.C_ALREADY.getCode());
        riskCheckRecordMapper.updateById(record);
        //修改隐患状态
        danger.setDangerStatus(Check.CheckInfo.D_CONFIRM.getCode());
        dangerService.updateById(danger);
        //生成预整改信息
        fixService.mySave(danger);
        return true;
    }

    @Override
    public boolean noAdoptionById(Long id) throws IllegalAccessException {
        RiskCheckRecord record = getById(id);
        //校验排查状态
        Check.checkEqualsStatus(record.getCheckStatus(), Check.CheckInfo.C_TO_CONFIRM, Check.CheckInfo.C_FORWARD);
        //校验权限
        RiskCheckDanger danger = dangerService.getByRecordId(id);
        SecurityUtils.hasUser(danger.getFixBy());
        //修改排查状态
        record.setCheckStatus(Check.CheckInfo.C_NO_ADOPTION.getCode());
        riskCheckRecordMapper.updateById(record);
        //修改隐患状态
        danger.setDangerStatus(Check.CheckInfo.D_NO_ADOPTION.getCode());
        dangerService.updateById(danger);
        return true;
    }

    @Override
    public boolean forwardById(RiskCheckVo vo) throws IllegalAccessException {
        RiskCheckRecord record = getById(vo.getId());
        //校验排查状态
        Check.checkEqualsStatus(record.getCheckStatus(), Check.CheckInfo.C_TO_CONFIRM, Check.CheckInfo.C_FORWARD);
        //校验权限
        RiskCheckDanger danger = dangerService.getByRecordId(vo.getId());
        SecurityUtils.hasUser(danger.getFixBy());
        //修改排查状态
        record.setCheckStatus(Check.CheckInfo.C_FORWARD.getCode());
        riskCheckRecordMapper.updateById(record);
        //修改整改责任人
        RiskCheckDanger checkDanger = vo.getCheckDanger();
        danger.setFixDept(checkDanger.getFixDept());
        danger.setFixBy(checkDanger.getFixBy());
        dangerService.updateById(danger);
        return true;
    }

    @Override
    public boolean deleteByIds(Long[] ids) {
        return riskCheckRecordMapper.deleteByIds(ids) > 0;
    }

    @Override
    public Date getBeginCheckTimeByTaskId(Long taskId) {
        return riskCheckRecordMapper.getBeginCheckTimeByTaskId(taskId);
    }

    /**
     * 新增排查记录
     *
     * @param task           任务信息
     * @param checkBeginTime 排查开始时间
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean taskSave(RiskCheckTask task, Date checkBeginTime) {
        RiskCheckRecord record = new RiskCheckRecord();
        record.setTaskId(task.getId());
        record.setSource(DangerSource.EVERYDAY.getCode());
        RiskMeasureVo measureVo = measureMapper.getInfoById(task.getMeasureId());
        record.setObjectId(measureVo.getObjectId());
        record.setUnitId(measureVo.getUnitId());
        record.setContent(measureVo.getContent());
        record.setImei(measureVo.getImei());
        record.setCheckDept(task.getCheckByDept());
        record.setIsDefend("0".equals(task.getTaskType()) ? "0" : "1");
        record.setCheckBeginTime(checkBeginTime);
        //计算排查截止时间
        // 存在任务时长：排查结束时间 = 排查开始时间 + 任务时长 - 1s，
        // 不存在任务时长：排查结束时间 = 排查开始时间 + 排查周期 - 1s
        Integer cycle = task.getLastCycle() == null ? task.getCycle() : task.getLastCycle();
        String cycleUnit = task.getLastCycleUnit() == null ? task.getCycleUnit() : task.getLastCycleUnit();
        Date checkEndTime = new Date();
        try {
            checkEndTime = DateUtils.addSecond(DateUtils.getNextDateByCycle(checkBeginTime, cycle, cycleUnit), -1);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        record.setCheckEndTime(checkEndTime);
        record.setCheckStatus(Check.CheckInfo.C_NO.getCode());
        Long createBy = task.getCreateBy();
        record.setCreateBy(createBy);
        record.setUpdateBy(createBy);
        return riskCheckRecordMapper.insert(record) > 0;
    }

}
